package com.zbkj.crmeb.order.pprocess;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.crmeb.core.exception.CrmebException;
import com.utils.monitor.DingMsgEnum;
import com.utils.monitor.DingTalkMsgUtil;
import com.zbkj.crmeb.agent.model.AgentAccount;
import com.zbkj.crmeb.agent.service.AgentAccountFlowService;
import com.zbkj.crmeb.agent.service.AgentAccountService;
import com.zbkj.crmeb.agent.service.AgentFreezeBillService;
import com.zbkj.crmeb.bill.model.MerFreezeBill;
import com.zbkj.crmeb.bill.service.MerFreezeBillService;
import com.zbkj.crmeb.chant.model.ChannelMerchantAccount;
import com.zbkj.crmeb.chant.service.IChannelMerchantAccountService;
import com.zbkj.crmeb.enums.AccountFlowTypeEnum;
import com.zbkj.crmeb.enums.OrderTradeTypeEnum;
import com.zbkj.crmeb.finance.request.FundsMonitorSearchRequest;
import com.zbkj.crmeb.front.request.OrderCreateRequest;
import com.zbkj.crmeb.front.response.ComputeOrderResponse;
import com.zbkj.crmeb.front.response.ConfirmOrderResponse;
import com.zbkj.crmeb.marketing.model.StoreCouponUser;
import com.zbkj.crmeb.marketing.service.StoreCouponUserService;
import com.zbkj.crmeb.store.model.*;
import com.zbkj.crmeb.store.request.StoreOrderRefundRequest;
import com.zbkj.crmeb.store.response.StoreCartResponse;
import com.zbkj.crmeb.store.service.*;
import com.zbkj.crmeb.store.utilService.OrderUtils;
import com.zbkj.crmeb.system.service.SystemAdminService;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.model.UserBill;
import com.zbkj.crmeb.user.request.UserOperateFundsRequest;
import com.zbkj.crmeb.user.service.UserBillService;
import com.zbkj.crmeb.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
public abstract class AbstractOrangePayOrderProcess implements IOrangePayOrderProcess {

    @Autowired
    private OrderUtils orderUtils;
    @Autowired
    private UserService userService;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    protected StoreOrderStatusService storeOrderStatusService;
    @Autowired
    private UserBillService userBillService;
    @Autowired
    private StoreAccountInfoService storeAccountInfoService;
    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;
    @Autowired
    private SystemAdminService systemAdminService;
    @Autowired
    private UserCommissionService userCommissionService;
    @Autowired
    private IChannelMerchantAccountService channelMerchantAccountService;
    @Autowired
    private AccountFlowService accountFlowService;
    @Autowired
    private StoreOrderInfoService storeOrderInfoService;
    @Autowired
    private MerFreezeBillService merFreezeBillService;
    @Autowired
    StoreCouponUserService storeCouponUserService;
    @Autowired
    AgentAccountService agentAccountService;
    @Autowired
    AgentFreezeBillService agentFreezeBillService;
    @Autowired
    AgentAccountFlowService agentAccountFlowService;
    @Autowired
    private StoreOrderRefundApplyService storeOrderRefundApplyService;

    protected BigDecimal getPayPrice(String orderKey, OrderCreateRequest request) {
        User currentUser = userService.getInfo();
        if (orderUtils.checkOrderExist(orderKey, currentUser.getUid()))
            throw new CrmebException(orderKey + "订单已存在");

        if (!orderUtils.checkPayType(request.getPayType()))
            throw new CrmebException("暂不支持该支付方式，请刷新页面或者联系管理员");

        String existCacheOrder = orderUtils.cacheGetOrderInfo(userService.getUserIdException(), orderKey);
        if (null == existCacheOrder)
            throw new CrmebException("订单已过期,请刷新当前页面!");
        ConfirmOrderResponse cor = JSONObject.parseObject(existCacheOrder, ConfirmOrderResponse.class);

        ComputeOrderResponse computeOrderResponse = orderUtils.computedOrder(request, cor, orderKey);
        if (null == computeOrderResponse) {
            throw new CrmebException("计算失败");
        } else {
            return computeOrderResponse.getPayPrice();
        }
    }

    public StoreOrder createOrder(String key, OrderCreateRequest orderRequest, String ip) {
        User currentUser = userService.getInfo();
        // 检查订单是否存在
        if (orderUtils.checkOrderExist(key, currentUser.getUid()))
            throw new CrmebException(key + "订单已存在");

        // 检测支付方式
        if (!orderUtils.checkPayType(orderRequest.getPayType()))
            throw new CrmebException("暂不支持该支付方式，请刷新页面或者联系管理员");

        String existCacheOrder = orderUtils.cacheGetOrderInfo(userService.getUserIdException(), key);
        if (null == existCacheOrder)
            throw new CrmebException("订单已过期,请刷新当前页面!");
        DingTalkMsgUtil.sendMsg(DingMsgEnum.ORDER_PAY,"缓存订单数据："+existCacheOrder);
        ConfirmOrderResponse cor = JSONObject.parseObject(existCacheOrder, ConfirmOrderResponse.class);
        // 检查订单状态
        return orderUtils.createOrder(orderRequest, cor, orderRequest.getIsChannel(), orderRequest.getStoreId(), key);
    }

    public boolean goOnRefund(StoreOrderRefundRequest request, StoreOrder storeOrder, StoreOrderInfo storeOrderInfo) {
        //修改订单退款状态
        if (request.getType() == 1) {
            //查询申请记录
            StoreOrderRefundApply refundApply = storeOrderRefundApplyService.getOne(Wrappers.<StoreOrderRefundApply>lambdaQuery().eq(StoreOrderRefundApply::getInfoId, storeOrderInfo.getId()).orderByDesc(StoreOrderRefundApply::getId).last("LIMIT 1"));
            if(refundApply != null && refundApply.getProcessType() == null){
                refundApply.setProcessType(1);
                refundApply.setProcessTime(new Date());
                refundApply.setRefundPrice(request.getAmount());
                storeOrderRefundApplyService.updateById(refundApply);
            }
            storeOrderInfo.setRefundStatus(2);
            storeOrderInfo.setStatus(Constants.ORDER_STATUS_H5_REFUNDED);
            storeOrderInfo.setRefundPrice(request.getAmount());
        } else if (request.getType() == 2) {
            storeOrderInfo.setRefundStatus(3);
            storeOrderInfo.setRefundPrice(request.getAmount().add(storeOrderInfo.getRefundPrice()));
        } else {
            throw new CrmebException("选择退款状态错误");
        }
        boolean b = storeOrderInfoService.updateById(storeOrderInfo);
        if (!b) {
            storeOrderStatusService.saveRefund(storeOrderInfo.getOrderId(),storeOrderInfo.getChildOrderNumber(), request.getAmount(), "失败",storeOrderInfo.getRefundStatus() == 2);
            throw new CrmebException("订单更新失败");
        }else {
            if(request.getType() == 1){
                orderUtils.updateOrderStatus(storeOrderInfo.getOrderId());
            }
        }
        //TODO 发送模板消息, 异步
        Boolean payType = orderUtils.getPayType(storeOrder.getPayType());
        //退款成功
        storeOrderStatusService.saveRefund(storeOrderInfo.getOrderId(), storeOrderInfo.getChildOrderNumber(),request.getAmount(), null,storeOrderInfo.getRefundStatus() == 2);
        //新增退款佣金记录
        if(storeOrderInfo.getStatus().equals(Constants.ORDER_STATUS_H5_REFUNDED)){
            userCommissionService.refundCommission(storeOrderInfo);
        }
        //新增账户明细
        addAccountInfo(storeOrder,storeOrderInfo, request.getAmount());
        //商户信息
        ChannelMerchantAccount merchantAccount = new ChannelMerchantAccount().setMerId(storeOrder.getMerId());
        //解析storeOrderInfo
        StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
        StoreProductAttrValue attrInfo = storeCartResponse.getProductInfo().getAttrInfo();
        //根据订单号判断订单来源 --外部订单退款到可用余额(退货退款)
        if(storeOrder.getOrderId().contains("OT")){
            //外部订单,退款到商户可用余额
            merchantAccount.setAccount(attrInfo.getPaidPrice());
            channelMerchantAccountService.calcMoney(merchantAccount);
            log.info("外部订单退款,商户可用余额增加,商户:{},金额:{}",storeOrder.getMerId(), attrInfo.getPaidPrice());
            accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                    AccountFlowTypeEnum.PRODUCT,attrInfo.getPaidPrice(),null,null,"第三方订单退款");
        }else {
            //退款,商户冻结余额减少
            if(storeOrderInfo.getRefundStatus() == 2){
                //订单来源
                if(!Objects.equals(storeOrderInfo.getIsEurope(),1)){
                    BigDecimal firstAgentFrozen = BigDecimal.ZERO,
                            secondAgentFrozen = BigDecimal.ZERO;
                    //服务商
                    if(attrInfo.getSecondAgentCost() != null && attrInfo.getFirstAgentCost() != null){
                        //二级利润
                        secondAgentFrozen = attrInfo.getCost().subtract(attrInfo.getSecondAgentCost());
                        //一级利润
                        firstAgentFrozen = attrInfo.getSecondAgentCost().subtract(attrInfo.getFirstAgentCost());
                    }else if(attrInfo.getSecondAgentCost() == null && attrInfo.getFirstAgentCost() != null){
                        //一级利润
                        firstAgentFrozen = attrInfo.getCost().subtract(attrInfo.getFirstAgentCost());
                    }
                    if(attrInfo.getFirstAgentId() != null){
                        updateAgentFrozen(storeOrderInfo, attrInfo.getFirstAgentId(), firstAgentFrozen);
                    }
                    if(attrInfo.getSecondAgentId() != null){
                        updateAgentFrozen(storeOrderInfo, attrInfo.getSecondAgentId(), secondAgentFrozen);
                    }
                }
                //自主发货
                boolean autoFlag = Objects.equals(storeOrderInfo.getIsEurope(),1) || Objects.equals(storeOrderInfo.getAutonomous(),1);
                if(payType == null){
                    BigDecimal increaseAccount = autoFlag ? null : attrInfo.getCost().add(attrInfo.getTaxAndSecondPrice());
                    merchantAccount.setFreezeAccount(BigDecimal.ZERO)
                            .setAccount(increaseAccount);
                    channelMerchantAccountService.calcMoney(merchantAccount);
                    log.info("用户退货退款,减少商户微信收款余额，商户:{},金额:{}",storeOrder.getMerId(),request.getAmount());
                    accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                            AccountFlowTypeEnum.PRODUCT,increaseAccount,null,BigDecimal.ZERO,"订单退款");
                }else if(payType){
                    //盈利金额
                    BigDecimal profit = autoFlag ?  attrInfo.getPrice() : attrInfo.getPaidPrice().subtract(attrInfo.getCost()).subtract(attrInfo.getTaxAndSecondPrice());
                    if(profit.compareTo(BigDecimal.ZERO)<0){
                        BigDecimal price = profit.negate().add(attrInfo.getPaidPrice().subtract(request.getAmount()));
                        merchantAccount.setAccount(price);
                        channelMerchantAccountService.calcMoney(merchantAccount);
                        log.info("用户退货退款,增加商户商户可用金额，商户:{},金额:{}",storeOrder.getMerId(),price);
                        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                AccountFlowTypeEnum.PRODUCT,price,null,null,"订单退款");
                    }else {
                        BigDecimal price = profit.subtract(attrInfo.getPaidPrice().subtract(request.getAmount()));
                        //修改冻结账单
                        merFreezeBillService.updateAmountFrozen(storeOrderInfo,price);
                        log.info("用户退货退款,减少商户商户冻结金额，商户:{},金额:{}",storeOrder.getMerId(),price);
                        merchantAccount.setFreezeAccount(price.negate());
                        channelMerchantAccountService.calcMoney(merchantAccount);
                        //记录商户流水操作  冻结金额
                        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                                AccountFlowTypeEnum.PRODUCT,null,null,price.negate(),"订单退款");
                    }
                }else {
                    BigDecimal increaseAccount = autoFlag ? null :  attrInfo.getCost().add(attrInfo.getTaxAndSecondPrice());
                    merchantAccount.setWithdrawAccount(request.getAmount().negate())
                            .setAccount(increaseAccount);
                    channelMerchantAccountService.calcMoney(merchantAccount);
                    log.info("用户退货退款,减少商户微信收款余额，商户:{},金额:{}",storeOrder.getMerId(),request.getAmount());
                    accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                            AccountFlowTypeEnum.PRODUCT,increaseAccount,request.getAmount().negate(),null,"订单退款");
                }
                //返还优惠券,商户金额
                buckleCoupon(storeOrder,storeOrderInfo);
                //退积分,退商户金额
                buckleIntegral(storeOrder,storeOrderInfo,Constants.USER_BILL_CATEGORY_INTEGRAL, Constants.USER_BILL_TYPE_DEDUCTION, Constants.USER_BILL_TYPE_PAY_PRODUCT_INTEGRAL_BACK,request.getType());
            }else {
                if(payType == null){
                    merchantAccount.setAccount(BigDecimal.ZERO);
                    channelMerchantAccountService.calcMoney(merchantAccount);
                    log.info("补偿性退款,减少商户商户可用余额，商户:{},金额:{}",storeOrder.getMerId(),BigDecimal.ZERO);
                    //记录商户流水操作
                    accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                            AccountFlowTypeEnum.PRODUCT,BigDecimal.ZERO,null,null,"补偿性退款");
                }else if(payType){
                    //补偿性退款
                    merchantAccount.setAccount(request.getAmount().negate());
                    channelMerchantAccountService.calcMoney(merchantAccount);
                    log.info("补偿性退款,减少商户商户可用余额，商户:{},金额:{}",storeOrder.getMerId(),request.getAmount());
                    //记录商户流水操作
                    accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                            AccountFlowTypeEnum.PRODUCT,request.getAmount().negate(),null,null,"补偿性退款");
                }else {
                    //补偿性退款
                    merchantAccount.setWithdrawAccount(request.getAmount().negate());
                    channelMerchantAccountService.calcMoney(merchantAccount);
                    log.info("补偿性退款,减少商户微信收款余额，商户:{},金额:{}",storeOrder.getMerId(),request.getAmount());
                    //记录商户流水操作
                    accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                            AccountFlowTypeEnum.PRODUCT,null,request.getAmount().negate(),null,"补偿性退款");
                }
            }
        }
        //退货增加库存
        if (request.getType() == 1) {
            //自主发货不加库存
            if(!Objects.equals(storeOrderInfo.getAutonomous(),1)){
                storeProductAttrValueService.addProductValueStock(storeOrderInfo);
            }
        }
        return true;
    }

    public void updateAgentFrozen(StoreOrderInfo storeOrderInfo, Integer agentId, BigDecimal firstAgentFrozen) {
        AgentAccount agentAccount = new AgentAccount();
        agentAccount.setAgentId(agentId)
                .setFreezeAccount(firstAgentFrozen.negate());
        agentAccountService.calcMoney(agentAccount);
        log.info("用户退货退款,减少服务商冻结金额，服务商:{},金额:{}",agentId,firstAgentFrozen);
        agentAccountFlowService.saveAccountFlow(agentId,storeOrderInfo.getOrderId(),null,null,
                AccountFlowTypeEnum.PRODUCT,null,firstAgentFrozen.negate(),"订单退款");
        agentFreezeBillService.updateAmountFrozen(storeOrderInfo,firstAgentFrozen);
    }

    private void buckleCoupon(StoreOrder storeOrder, StoreOrderInfo storeOrderInfo){
        if(storeOrder.getCouponPrice().compareTo(BigDecimal.ZERO) < 1 || storeOrderInfo.getCouponPrice().compareTo(BigDecimal.ZERO) < 1){
            return;
        }
//        ChannelMerchantAccount entity = new ChannelMerchantAccount();
//        entity.setMerId(storeOrder.getMerId());
//        entity.setAccount(storeOrderInfo.getCouponPrice());
//        channelMerchantAccountService.calcMoney(entity);
//        //商户流水记录
//        accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
//                AccountFlowTypeEnum.PRODUCT,storeOrderInfo.getCouponPrice(),null,null,"客户退款时优惠券返还");
        int count = storeOrderInfoService.count(Wrappers.lambdaQuery(StoreOrderInfo.class).gt(StoreOrderInfo::getCouponPrice, BigDecimal.ZERO)
                .ne(StoreOrderInfo::getStatus, -2).eq(StoreOrderInfo::getOrderId, storeOrderInfo.getOrderId()));
        if(count < 1){
            //返还优惠券
            storeCouponUserService.rollbackByCancelOrder(storeOrder);
        }
    }

    private void buckleIntegral(StoreOrder storeOrder,StoreOrderInfo storeOrderInfo,String category, String type, String foundsType,Integer reType) {
        try {
            StoreCartResponse response = JSON.parseObject(storeOrderInfo.getInfo(),StoreCartResponse.class);
            StoreProductAttrValue attrInfo = response.getProductInfo().getAttrInfo();
            if(attrInfo.getUseIntegral().compareTo(BigDecimal.ZERO)<1){
                return;
            }
            //更新退款.抵扣的积分要加上
            UserOperateFundsRequest userOperateFundsRequest = new UserOperateFundsRequest();
            userOperateFundsRequest.setUid(storeOrder.getUid());
            userOperateFundsRequest.setValue(attrInfo.getUseIntegral());
            userOperateFundsRequest.setFoundsType(foundsType);
            userOperateFundsRequest.setType(1);
            userOperateFundsRequest.setFoundsCategory(category);
            userOperateFundsRequest.setTitle("退货");
            userOperateFundsRequest.setLinkId(storeOrder.getId().toString());
            //更新佣金/积分
            userService.updateFounds(userOperateFundsRequest, true);
        }catch (Exception e){
            throw new CrmebException("更新退款佣金/积分失败");
        }
    }

    private void addAccountInfo(StoreOrder storeOrder, StoreOrderInfo storeOrderInfo,BigDecimal refundPrice) {
        User user = userService.getById(storeOrder.getUid());
        StoreAccountInfo info = new StoreAccountInfo();
        info.setOrderId(storeOrderInfo.getChildOrderNumber());
        info.setUid(storeOrder.getUid());
        if (null != user) {
            info.setRealName(user.getNickname());
            info.setNowMoney(user.getNowMoney());
        }
        info.setTradeType(OrderTradeTypeEnum.REFUND.getType());
        info.setTradePrice(refundPrice);
        info.setPayType(storeOrder.getPayType());
        if (Constants.PAY_TYPE_WE_CHAT.equals(storeOrder.getPayType()) || Constants.PAY_TYPE_HK_PAY.equals(storeOrder.getPayType())) {
            info.setIsAccount(0);
        }
        info.setRemark("商品退款" + refundPrice);
        int operateId = 0;
        if (Objects.isNull(storeOrder.getActivityGroupId())){
            operateId = systemAdminService.getAdminId();
        }
        info.setOperateId(operateId);
        storeAccountInfoService.save(info);
    }

    /** 退款积分
     * @param request StoreOrderRefundRequest 退款参数
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    private void subtractBill(StoreOrder storeOrder,StoreProductAttrValue attrInfo,StoreOrderRefundRequest request, String category, String type, String foundsType,Integer reType) {
        try{
            FundsMonitorSearchRequest fundsMonitorSearchRequest = new FundsMonitorSearchRequest();
            fundsMonitorSearchRequest.setCategory(category);
            fundsMonitorSearchRequest.setType(type);
            fundsMonitorSearchRequest.setLinkId(request.getOrderId().toString());
            //fundsMonitorSearchRequest.setPm(1);
            PageParamRequest pageParamRequest = new PageParamRequest();
            pageParamRequest.setLimit(Constants.EXPORT_MAX_LIMIT);
            List<UserBill> list = userBillService.getList(fundsMonitorSearchRequest, pageParamRequest);
            if(null == list || list.size() < 1){
                return;
            }
            for (UserBill userBill : list) {
                User user = userService.getById(userBill.getUid());
                if(null == user){
                    continue;
                }
                //更新退款.抵扣的积分要加上
                UserOperateFundsRequest userOperateFundsRequest = new UserOperateFundsRequest();
                userOperateFundsRequest.setUid(user.getUid());
                userOperateFundsRequest.setValue(userBill.getNumber());
                userOperateFundsRequest.setFoundsType(foundsType);
                userOperateFundsRequest.setType(1);
                userOperateFundsRequest.setFoundsCategory(category);
                userOperateFundsRequest.setTitle("退货");
                userOperateFundsRequest.setLinkId("0");
                userService.updateFounds(userOperateFundsRequest, true); //更新佣金/积分
                /*if(category.equals(Constants.USER_BILL_CATEGORY_INTEGRAL)){
                    userBillService.saveRefundIntegralBill(request, user);
                }else{
                    userBillService.saveRefundBrokeragePriceBill(request, user);
                }*/
                //扣减积分对应增加商户余额

                if (reType == 1 && !(userBill.getNumber().compareTo(BigDecimal.ZERO) == 0)) {
                    ChannelMerchantAccount entity = new ChannelMerchantAccount();
                    entity.setMerId(storeOrder.getMerId());
                    entity.setAccount(attrInfo.getDeductionPrice());
                    channelMerchantAccountService.calcMoney(entity);
                    //商户流水记录
                    accountFlowService.saveAccountFlow(storeOrder.getMerId(),storeOrder.getId(),null,null,
                            AccountFlowTypeEnum.PRODUCT,storeOrder.getDeductionPrice(),null,null,"客户退款时积分返还");
                }
            }
        }catch (Exception e){
            throw new CrmebException("更新退款佣金/积分失败");
        }
    }

    /** 退款扣除积分/余额
     * @param request StoreOrderRefundRequest 退款参数
     * @author Mr.Zhang
     * @since 2020-06-10
     */
    private void subtractBill(StoreOrderRefundRequest request, String category, String type, String foundsType) {
        try {
            if (1 == request.getType()) {
                FundsMonitorSearchRequest fundsMonitorSearchRequest = new FundsMonitorSearchRequest();
                fundsMonitorSearchRequest.setCategory(category);
                fundsMonitorSearchRequest.setLinkId(request.getOrderId().toString());
                fundsMonitorSearchRequest.setPm(1);

                PageParamRequest pageParamRequest = new PageParamRequest();
                pageParamRequest.setLimit(Constants.EXPORT_MAX_LIMIT);
                List<UserBill> list = userBillService.getList(fundsMonitorSearchRequest, pageParamRequest);

                if (null == list || list.size() < 1) {
                    return;
                }

                for (UserBill userBill : list) {
                    UserBill bill = new UserBill();
                    BeanUtils.copyProperties(userBill, bill);
                    bill.setPm(0);
                    bill.setTitle(bill.getTitle() + "-退款");
                    userBillService.save(bill);
                }
            }
        } catch (Exception e) {
            throw new CrmebException("更新退款佣金/积分失败");
        }
    }
}
